#ifndef __OPERATIONS__
#define __OPERATIONS__

#include <string>
#include <inttypes.h>

#include "avr-core.h"

using namespace std;

class AVRCore;

class CoreOperation
{
public:
  typedef enum {
    ADCADD, ADIW, AND, ANDI, ASR, BSETCLR, BLDBST, BRBCBRBS, CALL, 
    CBISBI, COM, CPCPC, CPI, ORI,
    INVALID
  } OP;

  virtual int execute (uint16_t instruction, AVRCore& core) = 0;
  virtual uint16_t opcode () const = 0;
  virtual uint16_t mask () const = 0;

  static CoreOperation::OP op_from_string (const string& str);

private:
  static void string_to_lower (string& str);
};



class ADCADDOperation : public CoreOperation
{
public:
  virtual int execute (uint16_t instruction, AVRCore& core);
  virtual uint16_t opcode () const { return 0x0c00; }
  virtual uint16_t mask () const { return 0xec00; }
};



class ADIWOperation : public CoreOperation
{
public:
  virtual int execute (uint16_t instruction, AVRCore& core);
  virtual uint16_t opcode () const { return 0x9600; }
  virtual uint16_t mask () const { return 0xff00; }
};



class ANDOperation : public CoreOperation
{
public:
  virtual int execute (uint16_t instruction, AVRCore& core);
  virtual uint16_t opcode () const { return 0x2000; }
  virtual uint16_t mask () const { return 0xfc00; }
};



class ANDIOperation : public CoreOperation
{
public:
  virtual int execute (uint16_t instruction, AVRCore& core);
  virtual uint16_t opcode () const { return 0x7000; }
  virtual uint16_t mask () const { return 0xf000; }
};



class ASROperation : public CoreOperation
{
public:
  virtual int execute (uint16_t instruction, AVRCore& core);
  virtual uint16_t opcode () const { return 0x9405; }
  virtual uint16_t mask () const { return 0xfe0f; }
};



class BSETCLROperation : public CoreOperation
{
public:
  virtual int execute (uint16_t instruction, AVRCore& core);
  virtual uint16_t opcode () const { return 0x9408; }
  virtual uint16_t mask () const { return 0xff0f; }
};



class BLDBSTOperation : public CoreOperation
{
public:
  virtual int execute (uint16_t instruction, AVRCore& core);
  virtual uint16_t opcode () const { return 0xf800; }
  virtual uint16_t mask () const { return 0xfc08; }
};



class BRBCBRBSOperation : public CoreOperation
{
public:
  virtual int execute (uint16_t instruction, AVRCore& core);
  virtual uint16_t opcode () const { return 0xf000; }
  virtual uint16_t mask () const { return 0xf800; }
};



class CALLOperation : public CoreOperation
{
public:
  virtual int execute ( uint16_t instruction, AVRCore& core);
  virtual uint16_t opcode () const { return 0x940e; }
  virtual uint16_t mask () const { return 0xfe0e; }
};



class CBISBIOperation : public CoreOperation
{
public:
  virtual int execute (uint16_t instruction, AVRCore& core);
  virtual uint16_t opcode () const { return 0x9800; }
  virtual uint16_t mask () const { return 0xfd00; }
};



class COMOperation : public CoreOperation
{
public:
  virtual int execute (uint16_t instruction, AVRCore& core);
  virtual uint16_t opcode () const { return 0x9400; }
  virtual uint16_t mask () const { return 0xfe0f; }
};



class CPCPCOperation : public CoreOperation
{
public:
  virtual int execute (uint16_t instruction, AVRCore& core);
  virtual uint16_t opcode () const { return 0x0400; }
  virtual uint16_t mask () const { return 0xec00; }
};



class CPIOperation : public CoreOperation
{
public:
  virtual int execute (uint16_t instruction, AVRCore& core);
  virtual uint16_t opcode () const { return 0x3000; }
  virtual uint16_t mask () const { return 0xf000; }
};



class CPSEOperation : public CoreOperation
{
public:
  virtual int execute (uint16_t instruction, AVRCore& core);
  virtual uint16_t opcode () const { return 0x1000; }
  virtual uint16_t mask () const { return 0xfc00; }
};



class ORIOperation : public CoreOperation
{
public:
  virtual int execute (uint16_t instruction, AVRCore& core);
  virtual uint16_t opcode () const { return 0x6000; }
  virtual uint16_t mask () const { return 0xf000; }
};

#endif /* __OPERATIONS__ */
